package com.tengfei.main.question.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tengfei.common.constant.UserConstants;
import com.tengfei.common.core.domain.PageQuery;
import com.tengfei.common.core.page.TableDataInfo;
import com.tengfei.common.exception.ServiceException;
import com.tengfei.common.helper.DataBaseHelper;
import com.tengfei.common.utils.StringUtils;
import com.tengfei.main.question.domain.*;
import com.tengfei.main.question.domain.bo.*;
import com.tengfei.main.question.domain.vo.ObjectiveVo;
import com.tengfei.main.question.domain.vo.QbUserVo;
import com.tengfei.main.question.domain.vo.QuestionBankVo;
import com.tengfei.main.question.domain.vo.SubjectiveVo;
import com.tengfei.main.question.mapper.*;
import com.tengfei.main.question.service.IQuestionBankService;
import com.tengfei.main.system.domain.SysDept;
import com.tengfei.main.system.domain.SysUser;
import com.tengfei.main.system.mapper.SysDeptMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 题库Service业务层处理
 *
 * @author tengfei
 * @date 2022-07-28
 */
@Service
public class QuestionBankServiceImpl implements IQuestionBankService {

    @Resource
    private QuestionBankMapper baseMapper;
    @Resource
    private ObjectiveMapper objectiveMapper;
    @Resource
    private SubjectiveMapper subjectiveMapper;
    @Resource
    private QbQuMapper qbQuMapper;
    @Resource
    private QbUserMapper qbUserMapper;
    @Resource
    private SysDeptMapper deptMapper;

    /**
     * 查询题库
     */
    @Override
    public QuestionBankVo queryById(Long qbId) {
        return baseMapper.selectVoById(qbId);
    }

    /**
     * 查询题库列表
     */
    @Override
    public TableDataInfo<QuestionBankVo> queryPageList(QuestionBankBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<QuestionBank> lqw = buildQueryWrapper(bo);
        Page<QuestionBankVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询题库列表
     */
    @Override
    public List<QuestionBankVo> queryList(QuestionBankBo bo) {
        LambdaQueryWrapper<QuestionBank> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<QuestionBank> buildQueryWrapper(QuestionBankBo bo) {
        LambdaQueryWrapper<QuestionBank> lqw = Wrappers.lambdaQuery();
        lqw.like(StringUtils.isNotBlank(bo.getQbName()), QuestionBank::getQbName, bo.getQbName());
        lqw.eq(bo.getQbShow() != null, QuestionBank::getQbShow, bo.getQbShow());
        lqw.eq(bo.getQbPattern() != null, QuestionBank::getQbPattern, bo.getQbPattern());
        lqw.orderByDesc(QuestionBank::getUpdateTime);
        return lqw;
    }

    /**
     * 新增题库
     */
    @Override
    public Boolean insertByBo(QuestionBankBo bo) {
        QuestionBank add = BeanUtil.toBean(bo, QuestionBank.class);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setQbId(add.getQbId());
        }
        return flag;
    }

    /**
     * 修改题库
     */
    @Override
    public Boolean updateByBo(QuestionBankBo bo) {
        QuestionBank update = BeanUtil.toBean(bo, QuestionBank.class);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 批量删除题库
     */
    @Transactional
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids) {
        // TODO 删除题库应删除绑定的对应题目，需做出判断，不随意删除
        ids.forEach(id -> {
            // 删除绑定的客观题
            // 删除绑定的主观题
            qbQuMapper.delete(new QueryWrapper<QbQu>()
                    .eq("qb_id", id));
        });
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    /**
     * 题库批量绑定题目
     *
     * @param bos
     * @return
     */
    @Transactional
    @Override
    public Boolean insertBatchQuByBo(List<QbQuBo> bos) {
        List<QbQu> qbQus = BeanUtil.copyToList(bos, QbQu.class);
        return qbQuMapper.insertBatch(qbQus);
    }

    /**
     * 题库批量解绑题目
     *
     * @param bos
     * @return
     */
    @Transactional
    @Override
    public Boolean deleteBatchQuById(List<QbQuBo> bos) {
        bos.forEach(bo -> {
            qbQuMapper.delete(new LambdaQueryWrapper<QbQu>()
                    .eq(QbQu::getQbId, bo.getQbId())
                    .eq(QbQu::getQuId, bo.getQuId())
                    .eq(QbQu::getQuType, bo.getQuType()));
        });
        return true;
    }

    /**
     * 查询题库已绑定题目列表
     */
    @Override
    public TableDataInfo bindQuList(QbQuQueryBo bo, PageQuery pageQuery) {
        Page<QbQu> qbQuPage = qbQuMapper.selectPage(pageQuery.build(), new LambdaQueryWrapper<QbQu>()
                .eq(QbQu::getQbId, bo.getQbId())
                .eq(QbQu::getQuType, bo.getQuType()));
        // 题目id
        List<Long> quIds = qbQuPage.getRecords()
                .stream()
                .map(qbQu -> qbQu.getQuId())
                .collect(Collectors.toList());
        if (isObj(bo.getQuType())) {
            // 客观题
            Page<ObjectiveVo> objectiveVoPage = new Page<ObjectiveVo>()
                    .setTotal(qbQuPage.getTotal())
                    .setCurrent(qbQuPage.getCurrent())
                    .setSize(qbQuPage.getSize());
            if (quIds.size() > 0) {
                List<ObjectiveVo> objectives = objectiveMapper.selectVoList(buildQueryWrapper(bo, quIds, true));
                objectiveVoPage.setRecords(objectives);
            } else {
                objectiveVoPage.setRecords(new ArrayList<>());
            }
            return TableDataInfo.build(objectiveVoPage);
        } else {
            // 主观题
            Page<SubjectiveVo> subjectiveVoPage = new Page<SubjectiveVo>()
                    .setTotal(qbQuPage.getTotal())
                    .setCurrent(qbQuPage.getCurrent())
                    .setSize(qbQuPage.getSize());
            if (quIds.size() > 0) {
                List<SubjectiveVo> subjectiveVos = subjectiveMapper.selectVoList(buildQueryWrapper(bo, quIds, true));
                subjectiveVoPage.setRecords(subjectiveVos);
            } else {
                subjectiveVoPage.setRecords(new ArrayList<>());
            }
            return TableDataInfo.build(subjectiveVoPage);
        }
    }

    /**
     * 查询题库未绑定题目列表
     */
    @Override
    public TableDataInfo unBindQuList(QbQuQueryBo bo, PageQuery pageQuery) {
        List<Long> quIds = qbQuMapper.selectList(new LambdaQueryWrapper<QbQu>()
                .eq(QbQu::getQbId, bo.getQbId())
                .eq(QbQu::getQuType, bo.getQuType()))
                .stream()
                .map(qbQu -> qbQu.getQuId())
                .collect(Collectors.toList());
        if (isObj(bo.getQuType())) {
            IPage objectiveVoPage = objectiveMapper.selectVoPage(pageQuery.build(), buildQueryWrapper(bo, quIds, false));
            return TableDataInfo.build(objectiveVoPage);
        } else {
            IPage subjectiveVoPage = subjectiveMapper.selectVoPage(pageQuery.build(), buildQueryWrapper(bo, quIds, false));
            return TableDataInfo.build(subjectiveVoPage);
        }
    }

    /**
     * 查询题库已绑定用户列表
     */
    @Override
    public TableDataInfo<QbUserVo> bindUserList(QbUserBo bo, PageQuery pageQuery) {
        if (ObjectUtil.isNull(baseMapper.selectById(bo.getQbId()))) {
            throw new ServiceException("题库不存在");
        }
        Page<QbUserVo> qbUserVoPage = qbUserMapper.selectBindUserList(buildQueryWrapperUser(bo), pageQuery.build(), bo.getQbId());
        return TableDataInfo.build(qbUserVoPage);
    }

    /**
     * 查询题库未绑定用户列表
     */
    @Override
    public TableDataInfo<QbUserVo> unBindUserList(QbUserBo bo, PageQuery pageQuery) {
        if (ObjectUtil.isNull(baseMapper.selectById(bo.getQbId()))) {
            throw new ServiceException("题库不存在");
        }
        Page<QbUserVo> qbUserVoPage = qbUserMapper.selectUnBindUserList(buildQueryWrapperUser(bo), pageQuery.build(), bo.getQbId());
        return TableDataInfo.build(qbUserVoPage);
    }

    /**
     * 题库批量绑定用户
     */
    @Transactional
    @Override
    public boolean insertBatchUserByBo(List<QbUserBo> bos) {
        List<QbUser> qbUsers = BeanUtil.copyToList(bos, QbUser.class);
        return qbUserMapper.insertBatch(qbUsers);
    }

    /**
     * 题库批量解绑用户
     */
    @Transactional
    @Override
    public boolean deleteBatchUserById(List<QbUserBo> bos) {
        bos.forEach(bo -> {
            qbUserMapper.delete(new LambdaQueryWrapper<QbUser>()
                    .eq(QbUser::getUserId, bo.getUserId())
                    .eq(QbUser::getQbId, bo.getQbId()));
        });
        return true;
    }

    // 部门用户查询条件
    private Wrapper<SysUser> buildQueryWrapperUser(QbUserBo bo) {
        QueryWrapper<SysUser> wrapper = Wrappers.query();
        wrapper
                .eq("u.show_status", UserConstants.USER_NORMAL)
                .eq("u.status", UserConstants.USER_NORMAL)
                .like(StringUtils.isNotBlank(bo.getName()), "u.name", bo.getName())
                .and(ObjectUtil.isNotNull(bo.getDeptId()), w -> {
                    List<SysDept> deptList = deptMapper.selectList(new LambdaQueryWrapper<SysDept>()
                            .select(SysDept::getDeptId)
                            .apply(DataBaseHelper.findInSet(bo.getDeptId(), "ancestors")));
                    List<Long> ids = deptList.stream().map(SysDept::getDeptId).collect(Collectors.toList());
                    ids.add(bo.getDeptId());
                    w.in("u.dept_id", ids);
                });
        return wrapper;
    }

    // 题目查询条件
    private LambdaQueryWrapper buildQueryWrapper(ObjAndSubBo bo, List<Long> quIds, boolean isBind) {
        if (isObj(bo.getQuType())) {
            return new LambdaQueryWrapper<Objective>()
                    .in(isBind, Objective::getObjId, quIds)
                    .notIn(!isBind && quIds.size() > 0, Objective::getObjId, quIds)
                    .eq(Objective::getObjType, bo.getQuType())
                    .eq(ObjectUtil.isNotNull(bo.getQuGrand()), Objective::getObjGrand, bo.getQuGrand())
                    .like(ObjectUtil.isNotNull(bo.getSearchValue()), Objective::getObjContent, bo.getSearchValue())
                    .or()
                    .like(ObjectUtil.isNotNull(bo.getSearchValue()), Objective::getObjTag, bo.getSearchValue());
        } else {
            return new LambdaQueryWrapper<Subjective>()
                    .in(isBind, Subjective::getSubId, quIds)
                    .notIn(!isBind && quIds.size() > 0, Subjective::getSubId, quIds)
                    .eq(Subjective::getSubType, bo.getQuType())
                    .eq(ObjectUtil.isNotNull(bo.getQuGrand()), Subjective::getSubGrand, bo.getQuGrand())
                    .like(ObjectUtil.isNotNull(bo.getSearchValue()), Subjective::getSubContent, bo.getSearchValue())
                    .or()
                    .like(ObjectUtil.isNotNull(bo.getSearchValue()), Subjective::getSubTag, bo.getSearchValue());
        }

    }

    // 非空判断+界限判断+是否为客观题
    private boolean isObj(Integer quType) {
        if (quType.intValue() < 1 || quType.intValue() > 5) {
            throw new ServiceException("题目类型不符合规范");
        } else if (quType.intValue() >= 1 && quType.intValue() <= 3) {
            return true;
        } else {
            return false;
        }
    }
}
